import { validateNull } from '../util';
import { baseUrl } from './config'
import { autoLogin } from './login';

export enum HttpMethod {
  GET = 'GET',
  POST = 'POST',
  OPTIONS = 'OPTIONS',
  PUT = 'PUT',
  DELETE = 'DELETE'
}

// 常用header
export enum CommonHeaderEnum {
  'TENANT_ID' = 'TENANT-ID',
  'ENC_FLAG' = 'Enc-Flag',
  'AUTHORIZATION' = 'Authorization',
}


/**
 * @description: 声明业务数据类型
*/
export interface MyAwesomeData<T> {
  code: number
  msg: string
  data: T
}

/**
 * @description: HTTP请求配置
*/
export interface RequestConfig {
  /** API路径 */
  url: string
  /** Method类型 */
  method?: HttpMethod
  /** 接口返回数据 */
  data?: any
  /** 是否跳转传输token */
  skipToken?: boolean
  /** Header头部 */
  header?: any
}

// 重试次数为3次
export const restartTimes = 3;

// 请求拦截器:统一增加Authorization请求头
function requestInterceptor(config: RequestConfig) {
  // console.log("经过了请求拦截器")
  var access_token = wx.getStorageSync("access_token");
  return new Promise<RequestConfig>((resolve, reject) => {
    if (config.skipToken) {
      // 不需要添加token
      resolve(config);
    } else {
      // 保证先具有header这个字段
      config.header = {};
      // console.log("获取的token为",access_token);
      if (validateNull(access_token)) {
        console.log("发现token为空");
        autoLogin().then(() => {
          access_token = wx.getStorageSync("access_token");
          config.header[CommonHeaderEnum.AUTHORIZATION] = `Bearer ${access_token}`;
          resolve(config);
        }).catch((err: any) => {
          console.log('登录获取token失败');
          reject(err)
        })
      } else {
        config.header[CommonHeaderEnum.AUTHORIZATION] = `Bearer ${access_token}`;
        resolve(config);
      }
    }
  });
}

// 响应拦截器: 符合错误重试的响应并完成重试，特殊424HTTP为令牌状态已过期，需要重新登录
function responseInterceptor(response: any) {
  // console.log("经过响应拦截器")
  return new Promise((resolve, reject) => {
    const resData = response.data
    if (validateNull(resData)) {
      // 这里返回所有响应值方便查看是什么HTTP异常编码
      reject(response)
    }
    // 处理响应结果
    // 如果不是正常带有code的结果，直接返回即可
    if (validateNull(resData.code)) {
      // 如果不带code，直接认为是正确
      // 需要校验status字段
      if (resData.status) {
        if (resData.status == 500 && resData.error.indexOf("Internal Server Error") != -1) {
          // 重试
          reject({ ...resData, reStart: true })
        } else {
          // 真错误
          reject(resData)
        }
      } 
      resolve(response);
    }

    if (resData.code == 0) {
      // code为0是正确
      resolve(response);
    } else {
      // code1 认为是错误，外部需要catch获取错误时的参数
      if (response.data.msg.indexOf("等待一段时间") != -1 || response.data.msg.indexOf("Redis exception") != -1) {
        reject({ ...response, reStart: true })
      } else {
        reject(response)
      }
    }
  });
}

export const request = (requestConfig: RequestConfig, showLoading: boolean = true, times: number = restartTimes) => {
  // 默认展示加载框
  return new Promise((resolve, reject) => {
    if (showLoading) {
      wx.showLoading({
        title: '加载中',
        mask: true
      })
    }
    // 请求拦截器
    requestInterceptor(requestConfig).then((config: RequestConfig) => {
      wx.request({
        url: baseUrl + config.url,
        method: config.method,
        data: config.data,
        header: config.header,
        success: (res: any) => {
          // 响应拦截器
          responseInterceptor(res).then((res: any) => {
            // 直接返回body，方便调用
            wx.hideLoading()
            resolve(res.data)
          }).catch((err: any) => {
            console.log("响应拦截器异常", err);
            console.log("剩余重试次数 " +times,"是否允许重试: ",err.reStart);
            // 重试
            if (times > 0 && err.reStart) {
              request(config, showLoading, times - 1).then((res: any) => {
                wx.hideLoading()
                resolve(res);
              })
            } else {
              wx.hideLoading()
              wx.showToast({
                title: '接口出现问题',
                icon: "loading"
              })
              console.log('访问接口：' + config.url + '出现问题', err);
              // 直接返回body，方便调用
              reject(err.data);
            }
          })
        },
        fail: (err: any) => {
          wx.hideLoading()
          console.log("微信发送请求失败");
          reject(err)
        }
      })
    }).catch((err: any) => {
      wx.hideLoading()
      reject(err)
    })
  })
}